#include "stdafx.h"
#include <cassert>

#include "LokiFakeDirect3D9.h"

LokiFakeDirect3D9 *LokiFakeDirect3D9::GetInstance()
{
	return new LokiFakeDirect3D9();
}

LokiFakeDirect3D9::LokiFakeDirect3D9()
	: LokiFakeUnknown(),
	_registerSoftwareDeviceInputs(),
	_registerSoftwareDeviceOutputs(),
	_registerSoftwareDeviceOutputCount(0),
	_getAdapterCountOutputs(),
	_getAdapterCountOutputCount(0),
	_getAdapterIdentifierInputs(),
	_getAdapterIdentifierOutputs(),
	_getAdapterIdentifierOutputCount(0),
	_enumAdapterModesInputs(),
	_enumAdapterModesOutputs(),
	_enumAdapterModesOutputCount(0),
	_getAdapterDisplayModeInputs(),
	_getAdapterDisplayModeOutputs(),
	_getAdapterDisplayModeOutputCount(0)
{
}

/*** IDirect3D9 methods ***/
HRESULT LokiFakeDirect3D9::RegisterSoftwareDevice(void* pInitializeFunction)
{
	RegisterSoftwareDeviceInputs inputs;
	Loki::Field<0>(inputs) = pInitializeFunction;
	_registerSoftwareDeviceInputs.push_back(inputs);
	RegisterSoftwareDeviceOutputs outputs = _registerSoftwareDeviceOutputs[_registerSoftwareDeviceOutputCount++];
	return Loki::Field<0>(outputs);
}

UINT LokiFakeDirect3D9::GetAdapterCount()
{
	GetAdapterCountOutputs outputs = _getAdapterCountOutputs[_getAdapterCountOutputCount++];
	return Loki::Field<0>(outputs);
}

HRESULT LokiFakeDirect3D9::GetAdapterIdentifier(UINT Adapter,DWORD Flags,D3DADAPTER_IDENTIFIER9* pIdentifier)
{
	GetAdapterIdentifierInputs inputs;
	Loki::Field<0>(inputs) = Adapter;
	Loki::Field<1>(inputs) = Flags;
	Loki::Field<2>(inputs) = pIdentifier;
	_getAdapterIdentifierInputs.push_back(inputs);

	GetAdapterIdentifierOutputs outputs = _getAdapterIdentifierOutputs[_getAdapterIdentifierOutputCount++];
	*pIdentifier = Loki::Field<0>(outputs);
	return Loki::Field<1>(outputs);
}

UINT LokiFakeDirect3D9::GetAdapterModeCount(UINT Adapter,D3DFORMAT Format)
{
	GetAdapterModeCountInputs inputs;
	Loki::Field<0>(inputs) = Adapter;
	Loki::Field<1>(inputs) = Format;
	_getAdapterModeCountInputs.push_back(inputs);
	GetAdapterModeCountOutputs outputs = _getAdapterModeCountOutputs[_getAdapterModeCountOutputCount++];
	return Loki::Field<0>(outputs);
}

HRESULT LokiFakeDirect3D9::EnumAdapterModes(UINT Adapter,D3DFORMAT Format,UINT Mode,D3DDISPLAYMODE* pMode)
{
	EnumAdapterModesInputs inputs;
	Loki::Field<0>(inputs) = Adapter;
	Loki::Field<1>(inputs) = Format;
	Loki::Field<2>(inputs) = Mode;
	Loki::Field<3>(inputs) = pMode;
	_enumAdapterModesInputs.push_back(inputs);
	EnumAdapterModesOutputs outputs = _enumAdapterModesOutputs[_enumAdapterModesOutputCount++];
	*pMode = Loki::Field<0>(outputs);
	return Loki::Field<1>(outputs);
}

HRESULT LokiFakeDirect3D9::GetAdapterDisplayMode(UINT Adapter,D3DDISPLAYMODE* pMode)
{
	GetAdapterDisplayModeInputs inputs;
	Loki::Field<0>(inputs) = Adapter;
	Loki::Field<1>(inputs) = pMode;
	_getAdapterDisplayModeInputs.push_back(inputs);
	GetAdapterDisplayModeOutputs outputs = _getAdapterDisplayModeOutputs[_getAdapterDisplayModeOutputCount++];
	*pMode = Loki::Field<0>(outputs);
	return Loki::Field<1>(outputs);
}

HRESULT LokiFakeDirect3D9::CheckDeviceType(UINT Adapter,
									   D3DDEVTYPE DevType,
									   D3DFORMAT AdapterFormat,
									   D3DFORMAT BackBufferFormat,
									   BOOL bWindowed)
{
	CheckDeviceTypeInputs inputs;
	Loki::Field<0>(inputs) = Adapter;
	Loki::Field<1>(inputs) = DevType;
	Loki::Field<2>(inputs) = AdapterFormat;
	Loki::Field<3>(inputs) = BackBufferFormat;
	Loki::Field<4>(inputs) = bWindowed;
	_checkDeviceTypeInputs.push_back(inputs);
	CheckDeviceTypeOutputs outputs = _checkDeviceTypeOutputs[_checkDeviceTypeOutputCount++];
	return Loki::Field<0>(outputs);
}

HRESULT LokiFakeDirect3D9::CheckDeviceFormat(UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,
										 DWORD Usage,D3DRESOURCETYPE RType,D3DFORMAT CheckFormat)
{
	CheckDeviceFormatInputs inputs;
	Loki::Field<0>(inputs) = Adapter;
	Loki::Field<1>(inputs) = DeviceType;
	Loki::Field<2>(inputs) = AdapterFormat;
	Loki::Field<3>(inputs) = Usage;
	Loki::Field<4>(inputs) = RType;
	Loki::Field<5>(inputs) = CheckFormat;
	_checkDeviceFormatInputs.push_back(inputs);
	CheckDeviceFormatOutputs outputs = _checkDeviceFormatOutputs[_checkDeviceFormatOutputCount++];
	return Loki::Field<0>(outputs);
}

HRESULT LokiFakeDirect3D9::CheckDeviceMultiSampleType(UINT Adapter,D3DDEVTYPE DeviceType,
												  D3DFORMAT SurfaceFormat,BOOL Windowed,
												  D3DMULTISAMPLE_TYPE MultiSampleType,
												  DWORD* pQualityLevels)
{
	CheckDeviceMultiSampleTypeInputs inputs;
	Loki::Field<0>(inputs) = Adapter;
	Loki::Field<1>(inputs) = DeviceType;
	Loki::Field<2>(inputs) = SurfaceFormat;
	Loki::Field<3>(inputs) = Windowed;
	Loki::Field<4>(inputs) = MultiSampleType;
	Loki::Field<5>(inputs) = pQualityLevels;
	_checkDeviceMultiSampleTypeInputs.push_back(inputs);
	CheckDeviceMultiSampleTypeOutputs outputs = _checkDeviceMultiSampleTypeOutputs[_checkDeviceMultiSampleTypeOutputCount++];
	*pQualityLevels = Loki::Field<0>(outputs);
	return Loki::Field<1>(outputs);
}

HRESULT LokiFakeDirect3D9::CheckDepthStencilMatch(UINT Adapter,
											  D3DDEVTYPE DeviceType,
											  D3DFORMAT AdapterFormat,
											  D3DFORMAT RenderTargetFormat,
											  D3DFORMAT DepthStencilFormat)
{
	CheckDepthStencilMatchInputs inputs;
	Loki::Field<0>(inputs) = Adapter;
	Loki::Field<1>(inputs) = DeviceType;
	Loki::Field<2>(inputs) = AdapterFormat;
	Loki::Field<3>(inputs) = RenderTargetFormat;
	Loki::Field<4>(inputs) = DepthStencilFormat;
	_checkDepthStencilMatchInputs.push_back(inputs);
	CheckDepthStencilMatchOutputs outputs = _checkDepthStencilMatchOutputs[_checkDepthStencilMatchOutputCount++];
	return Loki::Field<0>(outputs);
}

HRESULT LokiFakeDirect3D9::CheckDeviceFormatConversion(UINT Adapter,
												   D3DDEVTYPE DeviceType,
												   D3DFORMAT SourceFormat,
												   D3DFORMAT TargetFormat)
{
	CheckDeviceFormatConversionInputs inputs;
	Loki::Field<0>(inputs) = Adapter;
	Loki::Field<1>(inputs) = DeviceType;
	Loki::Field<2>(inputs) = SourceFormat;
	Loki::Field<3>(inputs) = TargetFormat;
	_checkDeviceFormatConversionInputs.push_back(inputs);
	CheckDeviceFormatConversionOutputs outputs = _checkDeviceFormatConversionOutputs[_checkDeviceFormatConversionOutputCount++];
	return Loki::Field<0>(outputs);
}

HRESULT LokiFakeDirect3D9::GetDeviceCaps(UINT Adapter,D3DDEVTYPE DeviceType,D3DCAPS9* pCaps)
{
	GetDeviceCapsInputs inputs;
	Loki::Field<0>(inputs) = Adapter;
	Loki::Field<1>(inputs) = DeviceType;
	Loki::Field<2>(inputs) = pCaps;
	_getDeviceCapsInputs.push_back(inputs);
	GetDeviceCapsOutputs outputs = _getDeviceCapsOutputs[_getDeviceCapsOutputCount++];
	*pCaps = Loki::Field<0>(outputs);
	return Loki::Field<1>(outputs);
}

HMONITOR LokiFakeDirect3D9::GetAdapterMonitor(UINT Adapter)
{
	GetAdapterMonitorInputs inputs;
	Loki::Field<0>(inputs)= Adapter;
	_getAdapterMonitorInputs.push_back(inputs);
	GetAdapterMonitorOutputs outputs = _getAdapterMonitorOutputs[_getAdapterMonitorOutputCount++];
	return Loki::Field<0>(outputs);
}

HRESULT LokiFakeDirect3D9::CreateDevice(UINT Adapter,
									D3DDEVTYPE DeviceType,
									HWND hFocusWindow,
									DWORD BehaviorFlags,
									D3DPRESENT_PARAMETERS* pPresentationParameters,
									IDirect3DDevice9** ppReturnedDeviceInterface)
{
	CreateDeviceInputs inputs;
	Loki::Field<0>(inputs) = Adapter;
	Loki::Field<1>(inputs) = DeviceType;
	Loki::Field<2>(inputs) = hFocusWindow;
	Loki::Field<3>(inputs) = BehaviorFlags;
	Loki::Field<4>(inputs) = pPresentationParameters;
	Loki::Field<5>(inputs) = ppReturnedDeviceInterface;
	_createDeviceInputs.push_back(inputs);
	CreateDeviceOutputs outputs;
	*ppReturnedDeviceInterface = Loki::Field<0>(outputs);
	return Loki::Field<1>(outputs);
}
